improvement(mothership): add file patch tool#3712
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
@cursor review |
PR SummaryHigh Risk Overview Updates the workspace Extends Copilot server tools: Written by Cursor Bugbot for commit 5712ac4. Configure here. |
Greptile SummaryThis PR adds a Most security concerns raised in earlier review rounds have been resolved:
Remaining items:
Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant UI as PptxPreview (Browser)
participant Serve as /api/files/serve
participant Preview as /api/workspaces/[id]/pptx/preview
participant VM as pptx-vm.ts
participant Worker as pptx-worker.cjs (subprocess)
participant Storage as Workspace Storage
Note over UI: Non-streaming path
UI->>Serve: GET /api/files/serve/[key]?context=workspace
Serve->>Storage: Download file buffer
Storage-->>Serve: PptxGenJS source (text/x-pptxgenjs)
Serve->>VM: compilePptxIfNeeded(buffer, filename, workspaceId)
VM->>Worker: spawn node pptx-worker.cjs (env=PATH only)
Worker-->>VM: IPC ready
VM->>Worker: IPC { type: generate, code }
opt getFileBase64 call
Worker->>VM: IPC { type: getFile, fileReqId, fileId }
VM->>Storage: getWorkspaceFile + downloadWorkspaceFile
Storage-->>VM: file buffer
VM->>Worker: IPC { type: fileResult, data: base64 }
end
Worker-->>VM: IPC { type: result, data: base64 }
VM-->>Serve: compiled PPTX Buffer
Serve-->>UI: binary PPTX (application/vnd.openxmlformats...)
UI->>UI: renderPptxSlides → setSlides([...images])
Note over UI: Streaming path (debounced 500ms)
UI->>Preview: POST /api/workspaces/[id]/pptx/preview { code }
Preview->>VM: generatePptxFromCode(code, workspaceId, req.signal)
VM->>Worker: spawn + generate (same IPC flow)
Worker-->>VM: result
VM-->>Preview: Buffer
Preview-->>UI: binary PPTX
UI->>UI: renderPptxSlides → setSlides([...images])
Reviews (7): Last reviewed commit: "Add cache-busting timestamp to binary fi..." | Re-trigger Greptile |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Autofix Details
Bugbot Autofix prepared fixes for both issues found in the latest run.
- ✅ Fixed: Serve route passes undefined workspaceId breaking file references
- Both handleLocalFile and handleCloudProxy now extract workspaceId from the file key using parseWorkspaceFileKey and pass it to compilePptxIfNeeded.
- ✅ Fixed: Server-side code execution via unsandboxed new Function
- Replaced new Function() with vm.createContext() which creates an isolated context exposing only pptx and getFileBase64, blocking access to process and other Node.js globals.
Or push these changes by commenting:
@cursor push cccb0dcbe3
Preview (cccb0dcbe3)
diff --git a/apps/sim/app/api/files/serve/[...path]/route.ts b/apps/sim/app/api/files/serve/[...path]/route.ts
--- a/apps/sim/app/api/files/serve/[...path]/route.ts
+++ b/apps/sim/app/api/files/serve/[...path]/route.ts
@@ -6,6 +6,7 @@
import { generatePptxFromCode } from '@/lib/copilot/tools/server/files/workspace-file'
import { CopilotFiles, isUsingCloudStorage } from '@/lib/uploads'
import type { StorageContext } from '@/lib/uploads/config'
+import { parseWorkspaceFileKey } from '@/lib/uploads/contexts/workspace/workspace-file-manager'
import { downloadFile } from '@/lib/uploads/core/storage-service'
import { inferContextFromKey } from '@/lib/uploads/utils/file-utils'
import { verifyFileAccess } from '@/app/api/files/authorization'
@@ -138,10 +139,11 @@
const rawBuffer = await readFile(filePath)
const segment = filename.split('/').pop() || filename
const displayName = stripStorageKeyPrefix(segment)
+ const workspaceId = parseWorkspaceFileKey(filename)
const { buffer: fileBuffer, contentType } = await compilePptxIfNeeded(
rawBuffer,
displayName,
- undefined,
+ workspaceId || undefined,
raw
)
@@ -202,10 +204,11 @@
const segment = cloudKey.split('/').pop() || 'download'
const displayName = stripStorageKeyPrefix(segment)
+ const workspaceId = parseWorkspaceFileKey(cloudKey)
const { buffer: fileBuffer, contentType } = await compilePptxIfNeeded(
rawBuffer,
displayName,
- undefined,
+ workspaceId || undefined,
raw
)
diff --git a/apps/sim/lib/copilot/tools/server/files/workspace-file.ts b/apps/sim/lib/copilot/tools/server/files/workspace-file.ts
--- a/apps/sim/lib/copilot/tools/server/files/workspace-file.ts
+++ b/apps/sim/lib/copilot/tools/server/files/workspace-file.ts
@@ -1,3 +1,4 @@
+import vm from 'node:vm'
import { createLogger } from '@sim/logger'
import PptxGenJS from 'pptxgenjs'
import type { BaseServerTool, ServerToolContext } from '@/lib/copilot/tools/server/base-tool'
@@ -36,8 +37,19 @@
return `data:${mime};base64,${buffer.toString('base64')}`
}
- const fn = new Function('pptx', 'getFileBase64', `return (async () => { ${code} })()`)
- await fn(pptx, getFileBase64)
+ const sandbox = {
+ pptx,
+ getFileBase64,
+ __result: null as unknown,
+ }
+
+ vm.createContext(sandbox)
+
+ const wrappedCode = `(async () => { ${code} })()`
+ const script = new vm.Script(`__result = ${wrappedCode}`, { filename: 'pptx-code.js' })
+ script.runInContext(sandbox)
+ await sandbox.__result
+
const output = await pptx.write({ outputType: 'nodebuffer' })
return output as Buffer
}This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
- generatePptxFromCode now accepts an optional AbortSignal; when the signal fires (e.g. client disconnects mid-stream), done() is called which clears timers and kills the subprocess immediately rather than waiting for the 60s timeout - preview route passes req.signal so client-side AbortController.abort() (from the streaming debounce cleanup) propagates all the way to the worker process - Correct misleading comment in pptx-worker.cjs and pptx-vm.ts: vm.createContext is NOT a sandbox when non-primitives are in scope; the real security boundary is the subprocess + minimal env
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@greptile |
|
@cursor review |
|
@greptile |
|
@cursor review |
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel.tsx
Outdated
Show resolved
Hide resolved
|
@greptile |
|
@cursor review |
|
@greptile |
|
@cursor review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.


Summary
Add file patch tool, add pptx capability
Type of Change
Testing
Manual
Checklist